package hello.word.m2.maven.support;

//import lombok.NonNull;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.customizer.Bind;
import org.jdbi.v3.sqlobject.customizer.BindList;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.customizer.DefineList;
import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

import javax.annotation.Nullable;
import java.util.List;

@SuppressWarnings({ "unused" })
interface InternalCrudDao<ENTITY extends Entity<ID>, ID> extends SqlObject{
	// region CRUD

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlQuery("select count(*) from <tableName>")
	long internalCount(@Define("tableName") /*@NonNull*/ String tableName);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlQuery("select * from <tableName> order by <idColumnName> <orderType> limit <limit>")
	List<ENTITY> internalFindAll(@Define("tableName") /*@NonNull*/ String tableName,
                                 @Define("idColumnName") /*@NonNull*/ String idColumnName, @Define("orderType") /*@NonNull*/ OrderType orderType,
                                 @Define("limit") int limit);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlQuery("select * from <tableName> where <conditions> order by <idColumnName> desc")
	List<ENTITY> internalFindConditions(@Define("tableName") /*@NonNull*/ String tableName,
                                        @Define("conditions") /*@NonNull*/ String conditions, @Define("idColumnName") /*@NonNull*/ String idColumnName);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("update <tableName> set <columnName> = :value where <conditions>")
	int internalUpdateConditions(@Define("tableName") /*@NonNull*/ String tableName,
                                 @Define("columnName") /*@NonNull*/ String columnName, @Bind("value") /*@NonNull*/ Object value,
                                 @Define("conditions") /*@NonNull*/ String conditions);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlQuery("select * from <tableName> where <column> <operand> :value order by <idColumnName> desc")
	List<ENTITY> internalFind(@Define("tableName") /*@NonNull*/ String tableName, @Define("column") /*@NonNull*/ String column,
                              @Bind("value") @Nullable Object value, @Define("operand") /*@NonNull*/ String operand,
                              @Define("idColumnName") /*@NonNull*/ String idColumnName);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("truncate table <tableName>")
	void internalTruncate(@Define("tableName") /*@NonNull*/ String tableName);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("delete from <tableName> where <idColumnName> = :id")
	int internalDelete(@Define("tableName") /*@NonNull*/ String tableName,
                       @Define("idColumnName") /*@NonNull*/ String idColumnName, @Bind("id") /*@NonNull*/ ID id);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("insert into <tableName> (<columnList>) values (<valueList>)")
	void internalInsert(@Define("tableName") /*@NonNull*/ String tableName,
                        @DefineList("columnList") /*@NonNull*/ List<String> columnList,
                        @BindList("valueList") /*@NonNull*/ List<Object> valueList);

	@SqlUpdate("insert into <tableName> (<columnList>) values (<valueList>)")
	@GetGeneratedKeys
	ID internalInsertReturnID(@Define("tableName") /*@NonNull*/ String tableName,
                              @DefineList("columnList") /*@NonNull*/ List<String> columnList,
                              @BindList("valueList") /*@NonNull*/ List<Object> valueList);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("update <tableName> set <columnName> = :value where <idColumnName> = :id")
	void internalUpdate(@Define("tableName") /*@NonNull*/ String tableName,
                        @Define("columnName") /*@NonNull*/ String columnName, @Bind("value") @Nullable Object value,
                        @Define("idColumnName") /*@NonNull*/ String idColumnName, @Bind("id") /*@NonNull*/ ID id);

	/**
	 * Inner implementation. Not for Override!!!
	 */
	@SqlUpdate("update <tableName> set <columnName> = :value")
	int internalUpdateAll(@Define("tableName") /*@NonNull*/ String tableName,
                          @Define("columnName") /*@NonNull*/ String columnName, @Bind("value") @Nullable Object value);
	// endregion

	enum OrderType {
		ASC, DESC
	}
}